package cn.hyatt.auth.security.filter;

import cn.hyatt.auth.config.JwtProperties;
import cn.hyatt.auth.dto.auth.AuthInfo;
import cn.hyatt.auth.dto.systemUser.SystemUserVo;
import cn.hyatt.auth.security.entity.LoginUserDetails;
import cn.hyatt.auth.service.AuthCacheService;
import cn.hyatt.auth.service.SystemUserService;
import cn.hyatt.common.utils.JwtUtil;
import cn.hyatt.common.utils.StringTool;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Optional;

/**
 * Jwt 身份验证过滤器
 *
 * @author hyatt
 */
@Slf4j
@Component
@AllArgsConstructor
public class JwtAuthenticatedFilter extends OncePerRequestFilter {

    private JwtProperties jwtProperties;
    private SystemUserService systemUserService;
    private AuthCacheService authCacheService;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 获取Token请求头
        String tokenHeader = request.getHeader(jwtProperties.getTokenHeader());
        // 判断请求头是否符合
        if (tokenHeader != null && tokenHeader.startsWith(jwtProperties.getTokenPrefix())) {
            // 获取token内容
            String token = StringTool.removePrefix(tokenHeader, jwtProperties.getTokenPrefix());
            // 获取请求头参数
            Claims claims;
            try {
                claims = JwtUtil.parseJWT(jwtProperties.getSecretKey(), token);
            } catch (ExpiredJwtException e) {
                // 认证超时
                log.info("认证超时:{}", e.getMessage());
                return;
            } catch (IllegalArgumentException e) {
                // 非法参数异常
                log.info("非法参数异常:{}", e.getMessage());
                return;
            }
            // 获取登录用户信息
            Long userId = ((Double) claims.get("id")).longValue();
            Optional<AuthInfo> cacheTokenOptional = authCacheService.getAuthInfo(userId);
            if (cacheTokenOptional.isEmpty()) {
                // 非法参数异常
                log.info("Token已失效,请重新登录");
                return;
            } else {
                AuthInfo authInfo = cacheTokenOptional.get();
                // 判断是否为有效的Token
                if (authInfo.getAccessToken().equals(token)) {
                    Optional<SystemUserVo> optional = systemUserService.getCacheById(userId);
                    optional.ifPresent(vo -> {
                        LoginUserDetails loginUserDetails = new LoginUserDetails();
                        BeanUtils.copyProperties(vo, loginUserDetails);
                        //存入SecurityContextHolder
                        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUserDetails, null, loginUserDetails.getAuthorities());
                        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

                    });
                }
            }
        }
        filterChain.doFilter(request, response);
    }
}
